// KebabCaseToCamelCase
type KebabCaseToCamelCase<Str extends string> = Str extends `${infer Item}-${infer Rest}` ? `${Item}${KebabCaseToCamelCase<Capitalize<Rest>>}` : Str
type test1 = KebabCaseToCamelCase<'abin-is-good'>

// CamelCaseToKebabCase
type CamelCaseToKebabCase<Str extends string> = Str extends `${infer Frist}${infer Rest}` ? Frist extends Lowercase<Frist> ? `${Frist}${CamelCaseToKebabCase<Rest>}` : `-${Lowercase<Frist>}${CamelCaseToKebabCase<Rest>}` : Str
type test2 = CamelCaseToKebabCase<'abinIsGood'>

// chunk
type Chunk<Arr extends unknown[], ItemLen extends number, CurItem extends unknown[] = [], Res extends unknown[] = []> = Arr extends [infer Frist, ...infer Rest] ? CurItem['length'] extends ItemLen ?
    Chunk<Rest, ItemLen, [Frist], [...Res, CurItem]> : Chunk<Rest, ItemLen, [...CurItem, Frist], Res> : [...Res, CurItem]
type test3 = Chunk<[1, 2, 3, 4, 5], 2>

// TupleToNestedObject
type TupleToNestedObject<Tuple extends unknown[], Value> = 
    Tuple extends [infer First, ...infer Rest] 
    ? {
        [Key in First as Key extends keyof any ? Key : never]: Rest extends unknown[]
    ? TupleToNestedObject<Rest, Value>
    : Value
} : Value;
type test4 = TupleToNestedObject<['abin', 'is', 'good'], 'aaaa'>

// PartialObjectPropByKeys
type Copy<Obj extends Record<string, any>> = {
    [Key in keyof Obj]: Obj[Key]
}
type PartialObjectPropByKeys<Obj extends Record<string, any>, Key extends keyof any = keyof Obj> = Copy<Partial<Pick<Obj, Extract<keyof Obj, Key>>> & Omit<Obj, Key>>
interface Abin {
    name: string,
    age: number,
    address: string 
} 
type test5 = PartialObjectPropByKeys<Abin, 'name' | 'age'>


interface A{
    a: string,
    c: string
}
interface B{
    b: string
}
type test6 = Copy<A & B>

// 函数重载
declare function add(a: number, b: number): number
declare function add(a: string, b: string): string


interface Func {
    (name: string): string
    (name: number): number
}

type Func2 = ReturnType<((name: string) => string) & ((name: number) => number)>

type UnionToIntersection<U> = (U extends U ? (x: U) => unknown : never) extends (x: infer R) => unknown ? R : never
type UnionToFuncIntersection<T> = UnionToIntersection<T extends any ? () => T : never>
type f = ReturnType<UnionToFuncIntersection<((name: string) => string) & ((name: number) => number)>>

// UnionToTuple
type UnionToTuple<T> = UnionToIntersection<T extends any ? () => T : never> extends () => infer ReturnType ? [...UnionToTuple<Exclude<T, ReturnType>>, ReturnType] : []
type tt = UnionToTuple<"a" | "b" | "c"> 


// join

declare function join<Delimiter extends string>(delimiter: Delimiter) : <Items extends string[]>(...args: Items) => JoinType<Items, Delimiter>
type JoinType<Items extends any[], Delimiter extends string, Result extends string = ''> = Items extends [infer Cur, ...infer Rest] ? JoinType<Rest, Delimiter, `${Result}${Delimiter}${Cur & string}`> : RemoveFirstDelimiter<Result>
type RemoveFirstDelimiter<Str extends string> = Str extends `${infer _}${infer Rest}` ? Rest : Str
let test7 = join('-')('abin', 'is', 'good')

// DeepCamelize
type obj = {
    aaa_bbb: string;
    bbb_ccc: [
        'aaa',
        {
            ccc_ddd: string;
        },
        {
            ddd_eee: string;
            eee_fff: {
                fff_ggg: string;
            }
        }
    ]
}

type DeepCamelize<Obj extends Record<string, any>> = Obj extends unknown[] ? CamelizeArr<Obj> : {
    [Key in keyof Obj as Key extends `${infer First}_${infer Rest}` ? `${First}${Capitalize<Rest>}` : Key]: DeepCamelize<Obj[Key]>
}

type CamelizeArr<Arr> = Arr extends [infer First, ...infer Rest] ? [First extends Record<string, any> ? DeepCamelize<First> : never, ...CamelizeArr<Rest>] : []
type test8 = DeepCamelize<obj>

// AllKeyPath
type Obj2 = {
    a: {
        b: {
            b1: string
            b2: string
        }
        c: {
            c1: string;
            c2: string;
        }
    },
}

type res2 = Obj2[keyof Obj2]

type AllKeyPath<Obj extends Record<string, any>> = {
    [Key in keyof Obj]: Key extends string ? Obj[Key] extends Record<string, any> ? Key | `${Key}.${AllKeyPath<Obj[Key]>}` : Key : never
}[keyof Obj]


type test9 = AllKeyPath<Obj2>

// Defaultize
type Defaultize<A, B> = Pick<A, Exclude<keyof A, keyof B>> & Partial<Pick<A, Extract<keyof A, keyof B>>> & Partial<Pick<B, Exclude<keyof B, keyof A>>>
type A1 = {
    aaa: 111,
    bbb: 222
}
type B1 = {
    bbb: 222,
    ccc: 333
}

type test10 = Copy<Defaultize<A1, B1>>

